; void crear_arbol_huffman(nodo_lista_t **l, nodo_arbol_t **a);

%include "macros/personalizada.mac"
%include "macros/nodo_arbol_t.mac"
%include "macros/nodo_lista_t.mac"

extern lista_obtener_primero
extern lista_insertar_ordenado
extern calloc
extern free

%define ptr_der [ebp - 8]
%define ptr_izq [ebp - 4]
%define ptr_ptr_lista [ebp + 8]
%define ptr_ptr_arbol [ebp + 12]

global crear_arbol_huffman

section .text

crear_arbol_huffman:
	push ebp
	mov ebp, esp
	sub esp, 8
	push esi
	push edi
	push ebx
	
	mov edi, ptr_ptr_lista ; edi = ptr ptr lista.
	cmp dword [edi], 0 ; [edi] es el ptr lista.
	jne sigo ; Si es distinto de Null sigo.
	jmp fin ; Sino salto a fin.
	
sigo:
	
ciclo:
	mov dword ptr_der, 0 ; Limpiamos las variables locales.
	mov dword ptr_izq, 0 ; Limpiamos las variables locales.
	
	; Obtenemos en ptr_izq el ptr nodo lista del primer nodo.
	lea ebx, ptr_izq
	push ebx
	push edi
	call lista_obtener_primero
	add esp, 8
	
	; Nos fijamos si el ptr nodo lista que nos pasan es vacio.
	mov eax, ptr_izq
	cmp eax, 0
	jne sigo2
	jmp fin
	
sigo2:
	; Obtenemos en ptr_der el ptr nodo lista del "segundo nodo".
	lea ebx, ptr_der
	push ebx
	push edi
	call lista_obtener_primero
	add esp, 8
	
	; Nos fijamos si es vacio el prt nodo lista "derecho".
	mov eax, ptr_der
	cmp eax, 0
	je termino
	
	;fusionar ptr_izq con ptr_der, sumarle apariciones y ponerlo en salida(e insertarlo ordenado en la lista)
	mov ebx, ptr_izq
	mov ebx, [ebx + off_ptr_nodo_arbol_t_nl]
	mov ebx, [ebx + off_apariciones_na]
	mov eax, ptr_der
	mov eax, [eax + off_ptr_nodo_arbol_t_nl]
	mov eax, [eax + off_apariciones_na]
	add ebx, eax	;pongo en ebx la suma de las apariciones de los arboles.
	
	; Reservamos memoria para el nodo arbol fusion.
	push dword 21
	push dword 1
	call calloc
	add esp, 8
	cmp eax, 0
	je fin
	

	mov [eax + off_apariciones_na], ebx		; Seteamos la cantidad de apariciones.
											; Como calloc me setea en 0 no hace falta setear en NULL el resto.
	
	mov ebx, ptr_izq
	mov ebx, [ebx + off_ptr_nodo_arbol_t_nl]
	mov [eax + off_ptr_izq_na], ebx ;el primero es hijo izq
	mov [ebx + off_ptr_padre_na], eax
	
	mov edx, ptr_der
	mov edx, [edx + off_ptr_nodo_arbol_t_nl]
	mov [eax + off_ptr_der_na], edx ;el segundo es hijo der
	mov [edx + off_ptr_padre_na], eax
	
	; Reinsertar el arbol armado en alguno de los nodos obtenidos. En el izquierdo.
	mov ebx, ptr_izq
	mov [ebx + off_ptr_nodo_arbol_t_nl], eax
	mov dword[ebx + off_ptr_sig_nl], 0
	
	push ebx
	push edi
	call lista_insertar_ordenado
	add esp,8
	
	; Liberamos la memoria del puntero derecho.
	mov ebx, ptr_der
	push ebx
	call free
	add esp, 4
	
	jmp ciclo
	
termino:
	; Aca guardamos el arbol que vamos a devolver.	
	mov edi, ptr_izq
	mov edi, [edi + off_ptr_nodo_arbol_t_nl]
	mov esi, ptr_ptr_arbol
	mov [esi], edi
	
	; Liberamos la memoria del puntero izquierdo.
	mov edi, ptr_izq
	push edi
	call free
	add esp, 4
	
fin:
	pop ebx
	pop edi
	pop esi
	add esp, 8
	pop ebp
	ret
